import cv2 as cv
import numpy as np
import math


L45_transformed_points = []
L45_Reference_point_x = 0
L45_Reference_point_y = 0
def L45_direction(img):
    global L45_transformed_points
    global L45_Reference_point_x
    global L45_Reference_point_y
    # img = cv.imread("square2.png")
    # img = cv.resize(img, None, fx=0.5, fy=0.5, interpolation=cv.INTER_CUBIC)

    # 旋转45度
    # rows, cols ,_= img.shape
    # # cols-1 和 rows-1 是坐标限制
    # M1 = cv.getRotationMatrix2D(((cols - 1) / 2.0, (rows - 1) / 2.0), 45, 1)
    # img = cv.warpAffine(img, M1, (cols, rows))
    # M2 = cv.getRotationMatrix2D(((cols - 1) / 2.0, (rows - 1) / 2.0), -45, 1)
    # img = cv.warpAffine(img, M2, (cols, rows))
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)  # 转化为灰度图像

    # frame_bin = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 5)
    _, frame_bin = cv.threshold(gray, 130, 255, cv.THRESH_BINARY )  # 进行二值化
    # blur = cv.GaussianBlur(gray, (7, 7), 0)  # 高斯模糊

    kernel = np.ones((7, 7), np.uint8)
    dilation = cv.erode(frame_bin, kernel, iterations=1)

    cv.imshow("name", dilation)
    edges = cv.Canny(dilation, 100, 200)  # Canny查找边缘
    _, contours, hierarchy = cv.findContours(edges, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)  # 边缘检测

    vertex = []  # 储存矩形的四个顶点
    max_area = 50000  # 定义矩形最大面积
    min_area = 1000
    EPSILON_RATIO = 0.02  # 定义边长缩放比例
    # 判断是不是矩形
    if len(contours) == 0:
        return
    # print("*" * 10)
    for i in range(0, len(contours)):  #
        area = cv.contourArea(contours[i])
        # print("area is:", area)
        if cv.contourArea(contours[i]) <= max_area and cv.contourArea(contours[i]) >= min_area:
            epsilon = EPSILON_RATIO * cv.arcLength(contours[i], True)
            approx = cv.approxPolyDP(contours[i], epsilon, True)
            if len(approx) == 4:
                vertex.append(approx)

    # 获取中心点坐标
    centers = []
    for i in vertex:
        # 计算轮廓的边界框
        x, y, w, h = cv.boundingRect(i)
        # 计算矩形的中心点坐标
        cx = x + w // 2
        cy = y + h // 2
        centers.append([cx, cy])

    # 获取距离小于或等于设定的阈值的点的下标对
    # 相似度阈值设定为百分之一
    threshold = 30
    # 存储满足条件的点对的下标
    similar_indices = []
    # 遍历每对点进行比较
    n = len(centers)
    i_list = []
    j_list = []
    for i in range(n):
        if i not in i_list:
            for j in range(i + 1, n):
                if j not in j_list:
                    # 计算欧氏距离
                    x1, y1 = centers[i]
                    x2, y2 = centers[j]
                    distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
                    # print("distance is:", distance)
                    # 判断距离是否在阈值内
                    if distance <= threshold:
                        similar_indices.append((i, j))
                        i_list.append(i)
                        j_list.append(j)
                        break

    # print("centers is :",centers)
    # print("len is:",len(vertex))
    # print(vertex)
    # print("similar_indices is:", similar_indices)

    Filtered_vertices = []
    Filtered_center_points = []
    # 从相似的下标对中找出单独的矩形和中心点
    for similar_points_index in similar_indices:
        # 选择每个相似对中的第0个
        Filtered_vertices.append(vertex[similar_points_index[0]])
        Filtered_center_points.append(centers[similar_points_index[0]])
        # cv.circle(img, tuple(centers[similar_points_index[0]]), 10, (0, 0, 255), -1)

    L45_transformed_points = []
    if len(Filtered_center_points) == 9:
        cx = 0
        cy = 0
        for point in Filtered_center_points:
            cx += point[0]
            cy += point[1]
        avg_x = cx // len(Filtered_center_points)
        avg_y = cy // len(Filtered_center_points)

        distance_2 = []
        for point in Filtered_center_points:
            length = math.sqrt((point[0] - avg_x) ** 2 + (point[1] - avg_y) ** 2)
            distance_2.append(length)

        rectangles = list(zip(distance_2, Filtered_center_points, Filtered_vertices))


        # 将中心点坐标和对应的顶点坐标配对
        # rectangles = list(zip(Filtered_center_points, Filtered_vertices))
        # 按照中心点坐标的从上到下
        sorted_rectangles = sorted(rectangles, key=lambda x: x[0], reverse=True)

        # print("sorted_rectangles", sorted_rectangles)

        long_distance = sorted_rectangles[:4]
        short_distance = sorted_rectangles[4:8]

        sorted_by_x = sorted(long_distance, key=lambda x: x[1][0])
        # 找出最大和最小的 x 坐标对应的元组
        max_x_tuple = sorted_by_x[-1]
        min_x_tuple = sorted_by_x[0]

        # 按照 Filtered_center_points 中的 y 坐标进行排序
        sorted_by_y = sorted(rectangles, key=lambda x: x[1][1])
        # 找出最大和最小的 y 坐标对应的元组
        max_y_tuple = sorted_by_y[-1]
        min_y_tuple = sorted_by_y[0]

        left_top = 0
        left_bottom = 0
        right_top = 0
        right_bottom = 0
        for i in short_distance:
            if i[1][0] < avg_x and i[1][1] < avg_y:  # x<cen_x y< cen_y
                left_top = i
            elif i[1][0] < avg_x and i[1][1] > avg_y:  # x<cen_x y> cen_y
                left_bottom = i
            elif i[1][0] > avg_x and i[1][1] < avg_y:  # x>cen_x y< cen_y
                right_top = i
            elif i[1][0] > avg_x and i[1][1] > avg_y:  # x<cen_x y< cen_y
                right_bottom = i
        if left_top != 0 and left_bottom != 0 and right_top != 0 and right_bottom != 0:
            sorted_ponits = [min_x_tuple] + [left_top] + [min_y_tuple] + [left_bottom] + [sorted_rectangles[-1]] + [right_top] + \
                            [max_y_tuple] + [right_bottom] + [max_x_tuple]
            # print("sorted_ponits", sorted_ponits)
            # print(type(sorted_ponits))
            # length_sorted = [item[0] for item in sorted_ponits]
            # center_points_sorted = [item[1] for item in sorted_ponits]
            # vertices_sorted = [item[2] for item in sorted_ponits]
            length_sorted , center_points_sorted , vertices_sorted = zip(*sorted_ponits)

            # print("center_points_sorted", center_points_sorted)

            number = 0

            for i in center_points_sorted:
                cv.circle(img, tuple(i), 10, (0, 0, 255), -1)
                number += 1
                cv.putText(img, str(number), tuple(i), cv.FONT_HERSHEY_SIMPLEX, 3, (255, 0, 0), 2, cv.LINE_AA)
                L45_transformed_points.append(i)


            # # TODO 此处开始转换坐标为1的最左边的点
            if len(center_points_sorted) == 9:
                L45_Reference_point_x = 0
                L45_Reference_point_y = 0
                min_x = center_points_sorted[0][0]
                for i in vertices_sorted[0]:
                    if i[0][0] < min_x:
                        min_x = i[0][0]
                        L45_Reference_point_x = i[0][0]
                        L45_Reference_point_y = i[0][1]

                L45_transformed_points = []
                for (x, y) in center_points_sorted:
                    transformed_x = x - L45_Reference_point_x
                    transformed_y = -(y - L45_Reference_point_y)  # 取负号操作
                    L45_transformed_points.append((transformed_x, transformed_y))

    return img

